package com.application.race.manage.player.effect;
import org.apache.mina.core.buffer.IoBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.application.race.manage.DEF;
import com.application.race.manage.RacingRoom;
import com.application.race.manage.player.Player;
import com.application.race.manage.player.effect.skill.RepairEffect;
import com.application.race.manage.player.effect.skill.StrickEffect;
import com.core.action.ActionConstants;
import com.core.utils.GameUtils;
import com.core.utils.PushDataUtils;

public class EffectChecker {
	
	private static final Logger log = LoggerFactory
	.getLogger(EffectChecker.class);			
	RacingRoom room;

	public EffectChecker(RacingRoom room) {
		this.room = room;
	}

	int i = 0;

	public void updataEffect(Player car) {
		for (i = 0; i < car.effects.size(); i++) {
			Effect eft = car.effects.get(i);
			if (!eft.update(car)) {
				car.effects.remove(eft);
				i--;
			}
		}
	}

	public void unchainOneEffect(Player car, int cid) {

		for (i = 0; i < car.effects.size(); i++) {
			Effect eft = car.effects.get(i);
			if (eft.effectId == cid) {
				car.effects.remove(i);
				return;
			}
		}
		RemoveEffect rc = new RemoveEffect();
		rc.effectId = car.effectId++;
		rc.removeId = cid;
		rc.removeType=0;//remove an  effect of action
		this.room.actions.addEffect(rc);
	}

	public int isOnEffect(Player car, int eftType) {
		for (int i = 0; i < car.effects.size(); i++) {
			Effect eft = car.effects.get(i);
			if (eft.effectType == eftType)
				return eft.effectId;
		}
		return -1;
	}

	public void makeCaroticEft(Player car1, Player car2,
			boolean initiative) {
		// log.info(car1._userName+ "  "+dpls+"  "+initiative);
		if (car2.onCarotic) {
			int cid = isOnEffect(car2, Effect.EFFECT_TYPE_CAROTIC);
			if (DEF.random(100) < 40) {
				unchainOneEffect(car2, cid);

			}
		} else {
			if (!initiative)
				return;

			int caroticInc = car1.carInfo.caroticchance
					- car2.carInfo.uncaroticchance;

			caroticInc += getCaroticPlusGap(car1, car2);
			caroticInc += 20;
			if (DEF.random(100) < caroticInc) {
				CaroticEffect eft = new CaroticEffect();
				eft.startTime = System.currentTimeMillis();
				eft.maxTime = DEF.random(10, 20) * 1000;
				eft.effectId = car2.effectId++;
				eft.receiver = car2.actor.getId();
				eft.initiator = car1.actor.getId();
				this.room.actions.addEffect(eft);
				car2.effects.add(eft);
			}
		}
	}

	public double getDamagePlus(Player car1, Player car2, CrashEffect eft) {
		if (car1.onCarotic)
			return 1;
		int fatalAtkChance = car1.carInfo.fatalatkchance
				- car2.carInfo.unfatalatkchance;
		
		if (car2.onCarotic)
			fatalAtkChance += 20;
		fatalAtkChance += getFatalAtkPlusGap(car1, car2);
		if(fatalAtkChance<5)fatalAtkChance=5;
		double damagePlus = 1;
		if (DEF.random(100) < fatalAtkChance) {
			int fatalRange = DEF.random(100);
			if (fatalRange < 80) {
				eft.effectType = Effect.EFFECT_TYPE_UNDER_FATAL_ATK_L1;
			} else if (fatalRange < 96) {
				eft.effectType = Effect.EFFECT_TYPE_UNDER_FATAL_ATK_L2;
			} else {
				eft.effectType = Effect.EFFECT_TYPE_UNDER_FATAL_ATK_L3;
			}
			damagePlus = 1.0 + (fatalRange / 100.0);
		}

		return damagePlus;
	}

	public Effect checkCrash(Player car1, double power, Player car2,
			boolean initiative) {

		int dodgechance = car2.carInfo.dodgechance - car1.carInfo.undodgechance;
		if (DEF.random(100) < dodgechance) {
			DodgeEffect deft = new DodgeEffect();
			deft.effectId = car2.effectId++;
			deft.receiver = car2.actor.getId();
			deft.initiator = car1.actor.getId();
			room.actions.addEffect(deft);
			return deft;
		}
		car1.onCarotic = false;
		car2.onCarotic = false;
		int cid1 = isOnEffect(car1, Effect.EFFECT_TYPE_CAROTIC);
		int cid2 = isOnEffect(car2, Effect.EFFECT_TYPE_CAROTIC);
		if (cid1 > -1)
			car1.onCarotic = true;
		if (cid2 > -1)
			car2.onCarotic = true;
		// if(isOnEffect(car1,BaseEffect.EFFECT_TYPE_CAROTIC)>-1)damagePlus*=1+(DEF.random(20,
		// 100)/100);
		CrashEffect ceft = new CrashEffect();
		double damagePlus = 1;
		if (initiative && power > 0.30)
			damagePlus = getDamagePlus(car1, car2, ceft);

		double powerEft = (power * power) * 10 * damagePlus;
		int atk = 0;
		int dfs = 0;
		if (damagePlus > 1) {
			atk = car1.carInfo.maxatk;
		} else {
			atk = DEF.random(car1.carInfo.minatk, car1.carInfo.maxatk);

		}
		dfs = DEF.random(car2.carInfo.mindef, car2.carInfo.maxdef);
		if (car1.onCarotic)
			atk = (int) (atk / (DEF.random(10, 20) / 10.0));
		if (car2.onCarotic)
			atk = (int) (atk * (DEF.random(10, 20) / 10.0));
		double dmg = atk - dfs;

		dmg *= getDmgPlusGap(car1, car2);
		int car2DecBlood = (int) (dmg * powerEft);
		if (car2DecBlood > 0) {

			if (car2DecBlood >= car2.now_blood) {
				car2DecBlood = car2.now_blood;
				car1.totalKills++;
				car2.dead = true;
				car2.resetAction();
				car2.now_blood = 0;
			} else {
				car2.now_blood = car2.now_blood - car2DecBlood;
				if (damagePlus >=1.6)
					makeCaroticEft(car1, car2, initiative);

			}

			car1.totalDamage += car2DecBlood;
			ceft.effectId = car2.effectId++;
			ceft.initiator = car1.actor.getId();
			ceft.receiver = car2.actor.getId();
			ceft.nowBlood = car2.now_blood;
			ceft.absBlood = car2DecBlood;
			room.actions.addEffect(ceft);
		    //car1.effects.add(ceft);
			return ceft;

		} else {
			ResistEffect reft = new ResistEffect();
			reft.effectId = car2.effectId++;
			reft.receiver = car2.actor.getId();
			reft.initiator = car1.actor.getId();
			room.actions.addEffect(reft);
			return reft;
		}

	}
	public final static int CRASH_PART_HEAD = 0;
	public final static int CRASH_PART_FRONT = 1;
	public final static int CRASH_PART_BODY = 2;
	public final static int CRASH_PART_BACK = 3;
	public final static int CRASH_PART_TAIL = 4;

	private int getFatalAtkPlusGap(Player car1, Player car2) {
		int gap0 = 0;
		int gap1 = 0;
		switch (car1.crashPart) {
		case CRASH_PART_HEAD:
			break;
		case CRASH_PART_FRONT:
			gap0 = -5;
			break;
		case CRASH_PART_BODY:
			gap0 = -10;
			break;
		case CRASH_PART_BACK:
			gap0 = -20;
			break;
		case CRASH_PART_TAIL:
			gap0 = -40;
			break;
		}
		switch (car2.crashPart) {
		case CRASH_PART_HEAD:
			break;
		case CRASH_PART_FRONT:
			gap1 = -5;
			break;
		case CRASH_PART_BODY:
			gap1 = -10;
			break;
		case CRASH_PART_BACK:
			gap1 = -20;
			break;
		case CRASH_PART_TAIL:
			gap1 = -40;
			break;
		}
		//log.info("getFatalAtkPlusGap   " + (gap0 - gap1));
		return gap0 - gap1;
	}

	private int getCaroticPlusGap(Player car1, Player car2) {
		int gap0 = 0;
		int gap1 = 0;
		switch (car1.crashPart) {
		case CRASH_PART_HEAD:
			break;
		case CRASH_PART_FRONT:
			gap0 = -4;
			break;
		case CRASH_PART_BODY:
			gap0 = -8;
			break;
		case CRASH_PART_BACK:
			gap0 = -16;
			break;
		case CRASH_PART_TAIL:
			gap0 = -32;
			break;
		}
		switch (car2.crashPart) {
		case CRASH_PART_HEAD:
			break;
		case CRASH_PART_FRONT:
			gap1 = -4;
			break;
		case CRASH_PART_BODY:
			gap1 = -8;
			break;
		case CRASH_PART_BACK:
			gap1 = -16;
			break;
		case CRASH_PART_TAIL:
			gap1 = -32;
			break;
		}
		//log.info("getCaroticPlusGap      " + (gap0 - gap1));
		return gap0 - gap1;
	}

	private double getDmgPlusGap(Player car1, Player car2) {
		double gap0 = 1;
		double gap1 = 1;
		switch (car1.crashPart) {
		case CRASH_PART_HEAD:
			break;
		case CRASH_PART_FRONT:
			gap0 = 0.95;
			break;
		case CRASH_PART_BODY:
			gap0 = 0.85;
			break;
		case CRASH_PART_BACK:
			gap0 = 0.65;
			break;
		case CRASH_PART_TAIL:
			gap0 = 0.25;
			break;
		}
		switch (car2.crashPart) {
		case CRASH_PART_HEAD:
			break;
		case CRASH_PART_FRONT:
			gap1 = 0.95;
			break;
		case CRASH_PART_BODY:
			gap1 = 0.85;
			break;
		case CRASH_PART_BACK:
			gap1 = 0.65;
			break;
		case CRASH_PART_TAIL:
			gap1 = 0.25;
			break;
		}
		//log.info("getDmgPlusGap      " + (1 + (gap0 - gap1)));
		return 1 + (gap0 - gap1);
	}
}
